home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / ed.screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  29.3 KB  |  1,304 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/ed.screen.c,v 3.11 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * ed.screen.c: Editor/termcap-curses interface
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: ed.screen.c,v 3.11 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tc.h"
  43. #include "ed.defns.h"
  44.  
  45. /*
  46.  * We don't prototype these, cause some systems have them wrong!
  47.  */
  48. extern char *tgoto();
  49. extern char *tgetstr();
  50. extern char *tputs();
  51. extern int tgetent();
  52. extern int tgetflag();
  53. extern int tgetnum();
  54.  
  55.  
  56. /* #define DEBUG_LITERAL */
  57.  
  58. /*
  59.  * IMPORTANT NOTE: these routines are allowed to look at the current screen
  60.  * and the current possition assuming that it is correct.  If this is not
  61.  * true, then the update will be WRONG!  This is (should be) a valid
  62.  * assumption...
  63.  */
  64.  
  65. #define TC_BUFSIZE 2048
  66.  
  67. #define GoodStr(a) (tstr[a].str != NULL && tstr[a].str[0] != '\0')
  68. #define Str(a) tstr[a].str
  69. #define Val(a) tval[a].val
  70.  
  71. static struct {
  72.     char   *b_name;
  73.     int     b_rate;
  74. }       baud_rate[] = {
  75.  
  76. #ifdef B0
  77.     { "0", B0 },
  78. #endif
  79. #ifdef B50
  80.     { "50", B50 },
  81. #endif
  82. #ifdef B75
  83.     { "75", B75 },
  84. #endif
  85. #ifdef B110
  86.     { "110", B110 },
  87. #endif
  88. #ifdef B134
  89.     { "134", B134 },
  90. #endif
  91. #ifdef B150
  92.     { "150", B150 },
  93. #endif
  94. #ifdef B200
  95.     { "200", B200 },
  96. #endif
  97. #ifdef B300
  98.     { "300", B300 },
  99. #endif
  100. #ifdef B600
  101.     { "600", B600 },
  102. #endif
  103. #ifdef B900
  104.     { "900", B900 },
  105. #endif
  106. #ifdef B1200
  107.     { "1200", B1200 },
  108. #endif
  109. #ifdef B1800
  110.     { "1800", B1800 },
  111. #endif
  112. #ifdef B2400
  113.     { "2400", B2400 },
  114. #endif
  115. #ifdef B3600
  116.     { "3600", B3600 },
  117. #endif
  118. #ifdef B4800
  119.     { "4800", B4800 },
  120. #endif
  121. #ifdef B7200
  122.     { "7200", B7200 },
  123. #endif
  124. #ifdef B9600
  125.     { "9600", B9600 },
  126. #endif
  127. #ifdef EXTA
  128.     { "19200", EXTA },
  129. #endif
  130. #ifdef B19200
  131.     { "19200", B19200 },
  132. #endif
  133. #ifdef EXTB
  134.     { "38400", EXTB },
  135. #endif
  136. #ifdef B38400
  137.     { "38400", B38400 },
  138. #endif
  139.     { NULL, 0 }
  140. };
  141.  
  142. static struct termcapstr {
  143.     char   *name;
  144.     char   *long_name;
  145.     char   *str;
  146. }       tstr[] = {
  147.  
  148. #define T_al    0
  149.     {    "al",    "add new blank line",        NULL },
  150. #define T_bl    1
  151.     {    "bl",    "audible bell",            NULL },
  152. #define T_cd    2
  153.     {    "cd",    "clear to bottom",        NULL },
  154. #define T_ce    3
  155.     {    "ce",    "clear to end of line",        NULL },
  156. #define T_ch    4
  157.     {    "ch",    "cursor to horiz pos",        NULL },
  158. #define T_cl    5
  159.     {    "cl",    "clear screen",            NULL },
  160. #define    T_dc    6
  161.     {    "dc",    "delete a character",        NULL },
  162. #define    T_dl    7
  163.     {    "dl",    "delete a line",        NULL },
  164. #define    T_dm    8
  165.     {    "dm",    "start delete mode",        NULL },
  166. #define    T_ed    9
  167.     {    "ed",    "end delete mode",        NULL },
  168. #define    T_ei    10
  169.     {    "ei",    "end insert mode",        NULL },
  170. #define    T_fs    11
  171.     {    "fs",    "cursor from status line",    NULL },
  172. #define    T_ho    12
  173.     {    "ho",    "home cursor",            NULL },
  174. #define    T_ic    13
  175.     {    "ic",    "insert character",        NULL },
  176. #define    T_im    14 
  177.     {    "im",    "start insert mode",        NULL },
  178. #define    T_ip    15
  179.     {    "ip",    "insert padding",        NULL },
  180. #define    T_kd    16
  181.     {    "kd",    "sends cursor down",        NULL },
  182. #define    T_kl    17
  183.     {    "kl",    "sends cursor left",        NULL },
  184. #define T_kr    18
  185.     {    "kr",    "sends cursor right",        NULL },
  186. #define T_ku    19
  187.     {    "ku",    "sends cursor up",        NULL },
  188. #define T_md    20
  189.     {    "md",    "begin bold",            NULL },
  190. #define T_me    21
  191.     {    "me",    "end attributes",        NULL },
  192. #define T_nd    22
  193.     {    "nd",    "non destructive space",    NULL },
  194. #define T_se    23
  195.     {    "se",    "end standout",            NULL },
  196. #define T_so    24
  197.     {    "so",    "begin standout",        NULL },
  198. #define T_ts    25
  199.     {    "ts",    "cursor to status line",    NULL },
  200. #define T_up    26
  201.     {    "up",    "cursor up one",        NULL },
  202. #define T_us    27
  203.     {    "us",    "begin underline",        NULL },
  204. #define T_ue    28
  205.     {    "ue",    "end underline",        NULL },
  206. #define T_vb    29
  207.     {    "vb",    "visible bell",            NULL },
  208. #define T_DC    30
  209.     {    "DC",    "delete multiple chars",    NULL },
  210. #define T_DO    31
  211.     {    "DO",    "cursor down multiple",        NULL },
  212. #define T_IC    32
  213.     {    "IC",    "insert multiple chars",    NULL },
  214. #define T_LE    33
  215.     {    "LE",    "cursor left multiple",        NULL },
  216. #define T_RI    34
  217.     {    "RI",    "cursor right multiple",    NULL },
  218. #define T_UP    35
  219.     {    "UP",    "cursor up multiple",        NULL },
  220. #define T_str    36
  221.     {    NULL,    NULL,        NULL }
  222. };
  223.  
  224. static struct termcapval {
  225.     char   *name;
  226.     char   *long_name;
  227.     int     val;
  228. }       tval[] = {
  229. #define T_pt    0
  230.     {    "pt",    "can use physical tabs", 0 },
  231. #define T_li    1
  232.     {    "li",    "Number of lines",     0 },
  233. #define T_co    2
  234.     {    "co",    "Number of columns",     0 },
  235. #define T_km    3
  236.     {    "km",    "Has meta key",         0 },
  237. #define T_val    4
  238.     {    NULL, NULL,         0 }
  239. };
  240.  
  241. static bool me_all = 0;        /* does two or more of the attributes use me */
  242.  
  243. static    void    ReBufferDisplay    __P((void));
  244. static    void    TCalloc        __P((struct termcapstr *, char *)); 
  245.  
  246.  
  247. static void
  248. TCalloc(t, cap)
  249.     struct termcapstr *t;
  250.     char   *cap;
  251. {
  252.     static char termcap_alloc[TC_BUFSIZE];
  253.     char    termbuf[TC_BUFSIZE];
  254.     struct termcapstr *ts;
  255.     static int tloc = 0;
  256.     int     tlen, clen;
  257.  
  258.     if (cap == NULL || *cap == '\0') {
  259.     t->str = NULL;
  260.     return;
  261.     }
  262.     else
  263.     clen = strlen(cap);
  264.  
  265.     if (t->str == NULL)
  266.     tlen = 0;
  267.     else
  268.     tlen = strlen(t->str);
  269.  
  270.     /*
  271.      * New string is shorter; no need to allocate space
  272.      */
  273.     if (clen <= tlen) {
  274.     (void) strcpy(t->str, cap);
  275.     return;
  276.     }
  277.  
  278.     /*
  279.      * New string is longer; see if we have enough space to append
  280.      */
  281.     if (tloc + 3 < TC_BUFSIZE) {
  282.     (void) strcpy(t->str = &termcap_alloc[tloc], cap);
  283.     tloc += clen + 1;    /* one for \0 */
  284.     return;
  285.     }
  286.  
  287.     /*
  288.      * Compact our buffer; no need to check compaction, cause we know it
  289.      * fits...
  290.      */
  291.     tlen = 0;
  292.     for (ts = tstr; ts->name != NULL; ts++)
  293.     if (t != ts && ts->str != NULL && ts->str[0] != '\0') {
  294.         char   *ptr;
  295.  
  296.         for (ptr = ts->str; *ptr != '\0'; termbuf[tlen++] = *ptr++);
  297.         termbuf[tlen++] = '\0';
  298.     }
  299.     copy(termcap_alloc, termbuf, TC_BUFSIZE);
  300.     tloc = tlen;
  301.     if (tloc + 3 >= TC_BUFSIZE) {
  302.     stderror(ERR_NAME | ERR_TCNOSTR);
  303.     return;
  304.     }
  305.     (void) strcpy(t->str = &termcap_alloc[tloc], cap);
  306.     tloc += clen + 1;        /* one for \0 */
  307.     return;
  308. }
  309.  
  310.  
  311. /*ARGSUSED*/
  312. void
  313. TellTC(what)
  314.     char   *what;
  315. {
  316.     struct termcapstr *t;
  317.  
  318.     xprintf("\n\tTcsh thinks your terminal has the\n");
  319.     xprintf("\tfollowing characteristics:\n\n");
  320.     xprintf("\tIt has %d columns and %d lines\n",
  321.         Val(T_co), Val(T_li));
  322.     xprintf("\tIt has %s meta key\n", T_HasMeta ? "a" : "no");
  323.     xprintf("\tIt can%suse tabs\n", T_Tabs ? " " : "not ");
  324.  
  325.     for (t = tstr; t->name != NULL; t++)
  326.     xprintf("\t%25s (%s) == %s\n", t->long_name, t->name,
  327.         t->str && *t->str ? t->str : "(empty)");
  328.     xprintf("\n");
  329. }
  330.  
  331.  
  332. static void
  333. ReBufferDisplay()
  334. {
  335.     register int i;
  336.     Char  **b;
  337.     Char  **bufp;
  338.  
  339.     b = Display;
  340.     Display = NULL;
  341.     if (b != NULL) {
  342.     for (bufp = b; *bufp != NULL; bufp++)
  343.         xfree((ptr_t) * bufp);
  344.     xfree((ptr_t) b);
  345.     }
  346.     b = Vdisplay;
  347.     Vdisplay = NULL;
  348.     if (b != NULL) {
  349.     for (bufp = b; *bufp != NULL; bufp++)
  350.         xfree((ptr_t) * bufp);
  351.     xfree((ptr_t) b);
  352.     }
  353.     /* make this public, -1 to avoid wraps */
  354.     TermH = Val(T_co) - 1;
  355.     TermV = (INBUFSIZE * 4) / TermH + 1;
  356.     b = (Char **) xmalloc((size_t) (sizeof(Char *) * (TermV + 1)));
  357.     for (i = 0; i < TermV; i++)
  358.     b[i] = (Char *) xmalloc((size_t) (sizeof(Char) * (TermH + 1)));
  359.     b[TermV] = NULL;
  360.     Display = b;
  361.     b = (Char **) xmalloc((size_t) (sizeof(Char *) * (TermV + 1)));
  362.     for (i = 0; i < TermV; i++)
  363.     b[i] = (Char *) xmalloc((size_t) (sizeof(Char) * (TermH + 1)));
  364.     b[TermV] = NULL;
  365.     Vdisplay = b;
  366. }
  367.  
  368. void
  369. SetTC(what, how)
  370.     char   *what, *how;
  371. {
  372.     struct termcapstr *ts;
  373.     struct termcapval *tv;
  374.  
  375.     /*
  376.      * Do the strings first
  377.      */
  378.     setname("settc");
  379.     for (ts = tstr; ts->name != NULL; ts++)
  380.     if (strcmp(ts->name, what) == 0)
  381.         break;
  382.     if (ts->name != NULL) {
  383.     TCalloc(ts, how);
  384.     /*
  385.      * Reset variables
  386.      */
  387.     if (GoodStr(T_me) && GoodStr(T_ue))
  388.         me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
  389.     else
  390.         me_all = 0;
  391.     if (GoodStr(T_me) && GoodStr(T_se))
  392.         me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
  393.  
  394.     T_CanCEOL = GoodStr(T_ce);
  395.     T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
  396.     T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
  397.     T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
  398.     return;
  399.     }
  400.  
  401.     /*
  402.      * Do the numeric ones second
  403.      */
  404.     for (tv = tval; tv->name != NULL; tv++)
  405.     if (strcmp(tv->name, what) == 0)
  406.         break;
  407.  
  408.     if (tv->name != NULL) {
  409.     if (tv == &tval[T_pt] || tv == &tval[T_km]) {
  410.         if (strcmp(how, "yes") == 0)
  411.         tv->val = 1;
  412.         else if (strcmp(how, "no") == 0)
  413.         tv->val = 0;
  414.         else {
  415.         stderror(ERR_SETTCUS, tv->name);
  416.         return;
  417.         }
  418.         T_Tabs = Val(T_pt);
  419.         T_HasMeta = Val(T_km);
  420.         return;
  421.     }
  422.     else {
  423.         tv->val = atoi(how);
  424.         T_Cols = Val(T_co);
  425.         T_Lines = Val(T_li);
  426.         if (tv == &tval[T_co] || tv == &tval[T_li])
  427.         ChangeSize(Val(T_li), Val(T_co));
  428.         return;
  429.     }
  430.     }
  431.     stderror(ERR_NAME | ERR_TCCAP, what);
  432.     return;
  433. }
  434.  
  435.  
  436. /*
  437.  * Print the termcap string out with variable substitution
  438.  */
  439. void
  440. EchoTC(v)
  441.     Char  **v;
  442. {
  443.     char   *cap, *scap, cv[BUFSIZE];
  444.     int     arg_need, arg_cols, arg_rows;
  445.     int     verbose = 0, silent = 0;
  446.     char   *area;
  447.     static char *fmts = "%s\n", *fmtd = "%d\n";
  448.     char    buf[TC_BUFSIZE];
  449.  
  450.     area = buf;
  451.  
  452.     setname("echotc");
  453.  
  454.     tglob(v);
  455.     if (gflag) {
  456.     v = globall(v);
  457.     if (v == 0)
  458.         stderror(ERR_NAME | ERR_NOMATCH);
  459.     }
  460.     else
  461.     v = gargv = saveblk(v);
  462.     trim(v);
  463.  
  464.     if (!*v || *v[0] == '\0')
  465.     return;
  466.     if (v[0][0] == '-') {
  467.     switch (v[0][1]) {
  468.     case 'v':
  469.         verbose = 1;
  470.         break;
  471.     case 's':
  472.         silent = 1;
  473.         break;
  474.     default:
  475.         stderror(ERR_NAME | ERR_TCUSAGE);
  476.         break;
  477.     }
  478.     v++;
  479.     }
  480.     if (!*v || *v[0] == '\0')
  481.     return;
  482.     (void) strcpy(cv, short2str(*v));
  483.     if (strcmp(cv, "tabs") == 0) {
  484.     xprintf(fmts, T_Tabs ? "yes" : "no");
  485.     flush();
  486.     return;
  487.     }
  488.     else if (strcmp(cv, "meta") == 0) {
  489.     xprintf(fmts, Val(T_km) ? "yes" : "no");
  490.     flush();
  491.     return;
  492.     }
  493.     else if (strcmp(cv, "baud") == 0) {
  494.     int     i;
  495.  
  496.     for (i = 0; baud_rate[i].b_name != NULL; i++)
  497.         if (T_Speed == baud_rate[i].b_rate) {
  498.         xprintf(fmts, baud_rate[i].b_name);
  499.         flush();
  500.         return;
  501.         }
  502.     xprintf(fmtd, 0);
  503.     flush();
  504.     return;
  505.     }
  506.     else if (strcmp(cv, "rows") == 0 || strcmp(cv, "lines") == 0) {
  507.     xprintf(fmtd, Val(T_li));
  508.     flush();
  509.     return;
  510.     }
  511.     else if (strcmp(cv, "cols") == 0) {
  512.     xprintf(fmtd, Val(T_co));
  513.     flush();
  514.     return;
  515.     }
  516.  
  517.     /*
  518.      * Count home many values we need for this capability.
  519.      */
  520.     scap = tgetstr(cv, &area);
  521.     if (!scap || scap[0] == '\0') {
  522.     if (silent)
  523.         return;
  524.     else
  525.         stderror(ERR_NAME | ERR_TCCAP, cv);
  526.     }
  527.  
  528.     for (cap = scap, arg_need = 0; *cap; cap++)
  529.     if (*cap == '%')
  530.         switch (*++cap) {
  531.         case 'd':
  532.         case '2':
  533.         case '3':
  534.         case '.':
  535.         case '+':
  536.         arg_need++;
  537.         break;
  538.         case '%':
  539.         case '>':
  540.         case 'i':
  541.         case 'r':
  542.         case 'n':
  543.         case 'B':
  544.         case 'D':
  545.         break;
  546.         default:
  547.         /*
  548.          * hpux has lot's of them...
  549.          */
  550.         if (verbose)
  551.             stderror(ERR_NAME | ERR_TCPARM, *cap);
  552.         /* This is bad, but I won't complain */
  553.         break;
  554.         }
  555.  
  556.     switch (arg_need) {
  557.     case 0:
  558.     v++;
  559.     if (*v && *v[0]) {
  560.         if (silent)
  561.         return;
  562.         else
  563.         stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
  564.     }
  565.     (void) tputs(scap, 1, putraw);
  566.     break;
  567.     case 1:
  568.     v++;
  569.     if (!*v || *v[0] == '\0')
  570.         stderror(ERR_NAME | ERR_TCNARGS, cv, 1);
  571.     arg_rows = 0;
  572.     arg_cols = atoi(short2str(*v));
  573.     v++;
  574.     if (*v && *v[0]) {
  575.         if (silent)
  576.         return;
  577.         else
  578.         stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
  579.     }
  580.     (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, putraw);
  581.     break;
  582.     default:
  583.     /* This is wrong, but I will ignore it... */
  584.     if (verbose)
  585.         stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
  586.     case 2:
  587.     v++;
  588.     if (!*v || *v[0] == '\0') {
  589.         if (silent)
  590.         return;
  591.         else
  592.         stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
  593.     }
  594.     arg_cols = atoi(short2str(*v));
  595.     v++;
  596.     if (!*v || *v[0] == '\0') {
  597.         if (silent)
  598.         return;
  599.         else
  600.         stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
  601.     }
  602.     arg_rows = atoi(short2str(*v));
  603.     v++;
  604.     if (*v && *v[0]) {
  605.         if (silent)
  606.         return;
  607.         else
  608.         stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
  609.     }
  610.     (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, putraw);
  611.     break;
  612.     }
  613.     flush();
  614.     if (gargv) {
  615.     blkfree(gargv);
  616.     gargv = 0;
  617.     }
  618. }
  619.  
  620. bool    GotTermCaps = 0;
  621.  
  622. void
  623. BindArrowKeys()
  624. {
  625.     KEYCMD *map, *dmap;
  626.     int     i, j;
  627.     char   *p;
  628.     static struct {
  629.     int     key, fun;
  630.     }       ar[] =
  631.     {
  632.     { T_kd, F_DOWN_HIST },
  633.     { T_ku, F_UP_HIST   },
  634.     { T_kl, F_CHARBACK  },
  635.     { T_kr, F_CHARFWD   }
  636.     };
  637.  
  638.     if (!GotTermCaps)
  639.     return;
  640.     map = VImode ? CcAltMap : CcKeyMap;
  641.     dmap = VImode ? CcViCmdMap : CcEmacsMap;
  642.  
  643.     for (i = 0; i < 4; i++) {
  644.     p = tstr[ar[i].key].str;
  645.     if (p && *p) {
  646.         j = (unsigned char) *p;
  647.         /*
  648.          * Assign the arrow keys only if:
  649.          *
  650.          * 1. They are multi-character arrow keys and the user 
  651.          *    has not re-assigned the leading character, or 
  652.          *    has re-assigned the leading character to be F_XKEY
  653.          * 2. They are single arrow keys pointing to an unassigned key.
  654.          */
  655.         if (p[1] && (dmap[j] == map[j] || map[j] == F_XKEY)) {
  656.         AddXkey(str2short(p), XmapCmd(ar[i].fun), XK_CMD);
  657.         map[j] = F_XKEY;
  658.         }
  659.         else if (map[j] == F_UNASSIGNED) {
  660.         ClearXkey(map, str2short(p));
  661.         map[j] = ar[i].fun;
  662.         }
  663.     }
  664.     }
  665. }
  666.  
  667. static Char cur_atr = 0;    /* current attributes */
  668.  
  669. void
  670. SetAttributes(atr)
  671.     int     atr;
  672. {
  673.     atr &= ATTRIBUTES;
  674.     if (atr != cur_atr) {
  675.     if (me_all && GoodStr(T_me)) {
  676.         if (((cur_atr & BOLD) && !(atr & BOLD)) ||
  677.         ((cur_atr & UNDER) && !(atr & UNDER)) ||
  678.         ((cur_atr & STANDOUT) && !(atr & STANDOUT))) {
  679.         (void) tputs(Str(T_me), 1, putpure);
  680.         cur_atr = 0;
  681.         }
  682.     }
  683.     if ((atr & BOLD) != (cur_atr & BOLD)) {
  684.         if (atr & BOLD) {
  685.         if (GoodStr(T_md) && GoodStr(T_me)) {
  686.             (void) tputs(Str(T_md), 1, putpure);
  687.             cur_atr |= BOLD;
  688.         }
  689.         }
  690.         else {
  691.         if (GoodStr(T_md) && GoodStr(T_me)) {
  692.             (void) tputs(Str(T_me), 1, putpure);
  693.             if ((cur_atr & STANDOUT) && GoodStr(T_se)) {
  694.             (void) tputs(Str(T_se), 1, putpure);
  695.             cur_atr &= ~STANDOUT;
  696.             }
  697.             if ((cur_atr & UNDER) && GoodStr(T_ue)) {
  698.             (void) tputs(Str(T_ue), 1, putpure);
  699.             cur_atr &= ~UNDER;
  700.             }
  701.             cur_atr &= ~BOLD;
  702.         }
  703.         }
  704.     }
  705.     if ((atr & STANDOUT) != (cur_atr & STANDOUT)) {
  706.         if (atr & STANDOUT) {
  707.         if (GoodStr(T_so) && GoodStr(T_se)) {
  708.             (void) tputs(Str(T_so), 1, putpure);
  709.             cur_atr |= STANDOUT;
  710.         }
  711.         }
  712.         else {
  713.         if (GoodStr(T_se)) {
  714.             (void) tputs(Str(T_se), 1, putpure);
  715.             cur_atr &= ~STANDOUT;
  716.         }
  717.         }
  718.     }
  719.     if ((atr & UNDER) != (cur_atr & UNDER)) {
  720.         if (atr & UNDER) {
  721.         if (GoodStr(T_us) && GoodStr(T_ue)) {
  722.             (void) tputs(Str(T_us), 1, putpure);
  723.             cur_atr |= UNDER;
  724.         }
  725.         }
  726.         else {
  727.         if (GoodStr(T_ue)) {
  728.             (void) tputs(Str(T_ue), 1, putpure);
  729.             cur_atr &= ~UNDER;
  730.         }
  731.         }
  732.     }
  733.     }
  734. }
  735.  
  736. /* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */
  737. int
  738. CanWeTab()
  739. {
  740.     return (Val(T_pt));
  741. }
  742.  
  743. void
  744. MoveToLine(where)        /* move to line <where> (first line == 0) */
  745.     int     where;        /* as efficiently as possible; */
  746. {
  747.     int     del, i;
  748.  
  749.     if (where == CursorV)
  750.     return;
  751.  
  752.     if (where > TermV) {
  753. #ifdef DEBUG_SCREEN
  754.     xprintf("MoveToLine: where is ridiculous: %d\r\n", where);
  755.     flush();
  756. #endif /* DEBUG_SCREEN */
  757.     return;
  758.     }
  759.  
  760.     if ((del = where - CursorV) > 0) {
  761.     if ((del > 1) && GoodStr(T_DO))
  762.         (void) tputs(tgoto(Str(T_DO), del, del), del, putpure);
  763.     else {
  764.         for (i = 0; i < del; i++)
  765.         (void) putraw('\n');
  766.         CursorH = 0;    /* because the \n will become \r\n */
  767.     }
  768.     }
  769.     else {            /* del < 0 */
  770.     if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
  771.         (void) tputs(tgoto(Str(T_UP), -del, -del), -del, putpure);
  772.     else {
  773.         if (GoodStr(T_up))
  774.         for (i = 0; i < -del; i++)
  775.             (void) tputs(Str(T_up), 1, putpure);
  776.     }
  777.     }
  778.     CursorV = where;        /* now where is here */
  779. }
  780.  
  781. void
  782. MoveToChar(where)        /* move to character position (where) */
  783.     int     where;
  784. {                /* as efficiently as possible */
  785.     int     del, i;
  786.  
  787. mc_again:
  788.     if (where == CursorH)
  789.     return;
  790.  
  791.     if (where > (TermH + 1)) {
  792. #ifdef DEBUG_SCREEN
  793.     xprintf("MoveToChar: where is riduculous: %d\r\n", where);
  794.     flush();
  795. #endif /* DEBUG_SCREEN */
  796.     return;
  797.     }
  798.  
  799.     if (!where) {        /* if where is first column */
  800.     (void) putraw('\r');    /* do a CR */
  801.     CursorH = 0;
  802.     return;
  803.     }
  804.  
  805.     del = where - CursorH;
  806.  
  807.     if ((del < -4 || del > 4) && GoodStr(T_ch))
  808.     /* go there directly */
  809.     (void) tputs(tgoto(Str(T_ch), where, where), where, putpure);
  810.     else {
  811.     if (del > 0) {        /* moving forward */
  812.         if ((del > 4) && GoodStr(T_RI))
  813.         (void) tputs(tgoto(Str(T_RI), del, del), del, putpure);
  814.         else {
  815.         if (T_Tabs) {    /* if I can do tabs, use them */
  816.             if ((CursorH & 0370) != (where & 0370)) {
  817.             /* if not within tab stop */
  818.             for (i = (CursorH & 0370); i < (where & 0370); i += 8)
  819.                 (void) putraw('\t');    /* then tab over */
  820.             CursorH = where & 0370;
  821.             }
  822.         }
  823.         /* it's usually cheaper to just write the chars, so we do. */
  824.  
  825.         /* NOTE THAT so_write() WILL CHANGE CursorH!!! */
  826.         so_write(&Display[CursorV][CursorH], where - CursorH);
  827.  
  828.         }
  829.     }
  830.     else {            /* del < 0 := moving backward */
  831.         if ((-del > 4) && GoodStr(T_LE))
  832.         (void) tputs(tgoto(Str(T_LE), -del, -del), -del, putpure);
  833.         else {        /* can't go directly there */
  834.         /* if the "cost" is greater than the "cost" from col 0 */
  835.         if (T_Tabs ? (-del > ((where >> 3) + (where & 07)))
  836.             : (-del > where)) {
  837.             (void) putraw('\r');    /* do a CR */
  838.             CursorH = 0;
  839.             goto mc_again;    /* and try again */
  840.         }
  841.         for (i = 0; i < -del; i++)
  842.             (void) putraw('\b');
  843.         }
  844.     }
  845.     }
  846.     CursorH = where;        /* now where is here */
  847. }
  848.  
  849. void
  850. so_write(cp, n)
  851.     register Char *cp;
  852.     register int n;
  853. {
  854.     if (n <= 0)
  855.     return;            /* catch bugs */
  856.  
  857.     if (n > (TermH + 1)) {
  858. #ifdef DEBUG_SCREEN
  859.     xprintf("so_write: n is riduculous: %d\r\n", n);
  860.     flush();
  861. #endif /* DEBUG_SCREEN */
  862.     return;
  863.     }
  864.  
  865.     do {
  866.     if (*cp & LITERAL) {
  867.         extern Char *litptr[];
  868.         Char   *d;
  869.  
  870. #ifdef DEBUG_LITERAL
  871.         xprintf("so: litnum %d, litptr %x\r\n",
  872.             *cp & CHAR, litptr[*cp & CHAR]);
  873. #endif /* DEBUG_LITERAL */
  874.         for (d = litptr[*cp++ & CHAR]; *d & LITERAL; d++)
  875.         (void) putraw(*d & CHAR);
  876.         (void) putraw(*d);
  877.  
  878.     }
  879.     else
  880.         (void) putraw(*cp++);
  881.     CursorH++;
  882.     } while (--n);
  883. }
  884.  
  885.  
  886. void
  887. DeleteChars(num)        /* deletes <num> characters */
  888.     int     num;
  889. {
  890.     if (num <= 0)
  891.     return;
  892.  
  893.     if (!T_CanDel) {
  894. #ifdef DEBUG_EDIT
  895.     xprintf("   ERROR: cannot delete   \n");
  896. #endif /* DEBUG_EDIT */
  897.     flush();
  898.     return;
  899.     }
  900.  
  901.     if (num > TermH) {
  902. #ifdef DEBUG_SCREEN
  903.     xprintf("DeleteChars: num is riduculous: %d\r\n", num);
  904.     flush();
  905. #endif /* DEBUG_SCREEN */
  906.     return;
  907.     }
  908.  
  909.     if (GoodStr(T_DC))        /* if I have multiple delete */
  910.     if ((num > 1) || !GoodStr(T_dc)) {    /* if dc would be more expen. */
  911.         (void) tputs(tgoto(Str(T_DC), num, num), num, putpure);
  912.         return;
  913.     }
  914.  
  915.     if (GoodStr(T_dm))        /* if I have delete mode */
  916.     (void) tputs(Str(T_dm), 1, putpure);
  917.  
  918.     if (GoodStr(T_dc))        /* else do one at a time */
  919.     while (num--)
  920.         (void) tputs(Str(T_dc), 1, putpure);
  921.  
  922.     if (GoodStr(T_ed))        /* if I have delete mode */
  923.     (void) tputs(Str(T_ed), 1, putpure);
  924. }
  925.  
  926. void
  927. Insert_write(cp, num)        /* Puts terminal in insert character mode, */
  928.     register Char *cp;
  929.     register int num;        /* or inserts num characters in the line */
  930. {
  931.     if (num <= 0)
  932.     return;
  933.     if (!T_CanIns) {
  934. #ifdef DEBUG_EDIT
  935.     xprintf("   ERROR: cannot insert   \n");
  936. #endif /* DEBUG_EDIT */
  937.     flush();
  938.     return;
  939.     }
  940.  
  941.     if (num > TermH) {
  942. #ifdef DEBUG_SCREEN
  943.     xprintf("StartInsert: num is riduculous: %d\r\n", num);
  944.     flush();
  945. #endif /* DEBUG_SCREEN */
  946.     return;
  947.     }
  948.  
  949.     if (GoodStr(T_IC))        /* if I have multiple insert */
  950.     if ((num > 1) || !GoodStr(T_ic)) {    /* if ic would be more expen. */
  951.         (void) tputs(tgoto(Str(T_IC), num, num), num, putpure);
  952.         so_write(cp, num);    /* this updates CursorH */
  953.         return;
  954.     }
  955.  
  956.     if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
  957.     (void) tputs(Str(T_im), 1, putpure);
  958.  
  959.     CursorH += num;
  960.     do 
  961.         (void) putraw(*cp++);
  962.     while (--num);
  963.  
  964.     if (GoodStr(T_ip))    /* have to make num chars insert */
  965.         (void) tputs(Str(T_ip), 1, putpure);
  966.  
  967.     (void) tputs(Str(T_ei), 1, putpure);
  968.     return;
  969.     }
  970.  
  971.     do {
  972.     if (GoodStr(T_ic))    /* have to make num chars insert */
  973.         (void) tputs(Str(T_ic), 1, putpure);    /* insert a char */
  974.  
  975.     (void) putraw(*cp++);
  976.  
  977.     CursorH++;
  978.  
  979.     if (GoodStr(T_ip))    /* have to make num chars insert */
  980.         (void) tputs(Str(T_ip), 1, putpure);/* pad the inserted char */
  981.  
  982.     } while (--num);
  983.  
  984. }
  985.  
  986. void
  987. ClearEOL(num)            /* clear to end of line.  There are num */
  988.     int     num;        /* characters to clear */
  989. {
  990.     register int i;
  991.  
  992.     if (T_CanCEOL && GoodStr(T_ce))
  993.     (void) tputs(Str(T_ce), 1, putpure);
  994.     else {
  995.     for (i = 0; i < num; i++)
  996.         (void) putraw(' ');
  997.     CursorH += num;        /* have written num spaces */
  998.     }
  999. }
  1000.  
  1001. void
  1002. ClearScreen()
  1003. {                /* clear the whole screen and home */
  1004.     if (GoodStr(T_cl))
  1005.     /* send the clear screen code */
  1006.     (void) tputs(Str(T_cl), Val(T_li), putpure);
  1007.     else if (GoodStr(T_ho) && GoodStr(T_cd)) {
  1008.     (void) tputs(Str(T_ho), Val(T_li), putpure);    /* home */
  1009.     /* clear to bottom of screen */
  1010.     (void) tputs(Str(T_cd), Val(T_li), putpure);
  1011.     }
  1012.     else {
  1013.     (void) putraw('\r');
  1014.     (void) putraw('\n');
  1015.     }
  1016. }
  1017.  
  1018. void
  1019. Beep()
  1020. {                /* produce a sound */
  1021.     beep_cmd ();
  1022.     if (adrof(STRnobeep))
  1023.     return;
  1024.  
  1025.     if (GoodStr(T_vb) && adrof(STRvisiblebell))
  1026.     (void) tputs(Str(T_vb), 1, putpure);    /* visible bell */
  1027.     else if (GoodStr(T_bl))
  1028.     /* what termcap says we should use */
  1029.     (void) tputs(Str(T_bl), 1, putpure);
  1030.     else
  1031.     (void) putraw('\007');    /* an ASCII bell; ^G */
  1032. }
  1033.  
  1034. void
  1035. ClearToBottom()
  1036. {                /* clear to the bottom of the screen */
  1037.     if (GoodStr(T_cd))
  1038.     (void) tputs(Str(T_cd), Val(T_li), putpure);
  1039.     else if (GoodStr(T_ce))
  1040.     (void) tputs(Str(T_ce), Val(T_li), putpure);
  1041. }
  1042.  
  1043. void
  1044. GetTermCaps()
  1045. {                /* read in the needed terminal capabilites */
  1046.     register int i;
  1047.     char   *ptr;
  1048.     char    buf[TC_BUFSIZE];
  1049.     static char bp[TC_BUFSIZE];
  1050.     char   *area;
  1051.     extern char *getenv();
  1052.     struct termcapstr *t;
  1053.  
  1054.  
  1055. #ifdef SIG_WINDOW
  1056. # ifdef BSDSIGS
  1057.     sigmask_t omask;
  1058. # endif /* BSDSIGS */
  1059.     int     lins, cols;
  1060.  
  1061.     /* don't want to confuse things here */
  1062. # ifdef BSDSIGS
  1063.     omask = sigblock(sigmask(SIG_WINDOW)) & ~sigmask(SIG_WINDOW);
  1064. # else /* BSDSIGS */
  1065.     (void) sighold(SIG_WINDOW);
  1066. # endif /* BSDSIGS */
  1067. #endif /* SIG_WINDOW */
  1068.     area = buf;
  1069.  
  1070.     GotTermCaps = 1;
  1071.  
  1072.     setname("gettermcaps");
  1073.     ptr = getenv("TERM");
  1074.  
  1075. #ifdef apollo
  1076.     /*
  1077.      * If we are on a pad, we pretend that we are dumb. Otherwise the termcap
  1078.      * library will put us in a weird screen mode, thinking that we are going
  1079.      * to use curses
  1080.      */
  1081.     if (isapad())
  1082.     ptr = "dumb";
  1083. #endif /* apollo */
  1084.  
  1085.     if (!ptr || !ptr[0])
  1086.     ptr = "dumb";
  1087.  
  1088.     setzero(bp, TC_BUFSIZE);
  1089.  
  1090.     i = tgetent(bp, ptr);
  1091.     if (i <= 0) {
  1092.     if (i == -1) {
  1093. #if (SVID == 0) || defined(IRIS3D)
  1094.         xprintf("tcsh: Cannot open /etc/termcap.\n");
  1095.     }
  1096.     else if (i == 0) {
  1097. #endif /* SVID */
  1098.         xprintf("tcsh: No entry for terminal type \"%s\"\n",
  1099.             getenv("TERM"));
  1100.     }
  1101.     xprintf("tcsh: using dumb terminal settings.\n");
  1102.     Val(T_co) = 80;        /* do a dumb terminal */
  1103.     Val(T_pt) = Val(T_km) = Val(T_li) = 0;
  1104.     for (t = tstr; t->name != NULL; t++)
  1105.         TCalloc(t, NULL);
  1106.     }
  1107.     else {
  1108.     /* Can we tab */
  1109.     Val(T_pt) = tgetflag("pt") && !tgetflag("xt");
  1110.     /* do we have a meta? */
  1111.     Val(T_km) = (tgetflag("km") || tgetflag("MT"));
  1112.     Val(T_co) = tgetnum("co");
  1113.     Val(T_li) = tgetnum("li");
  1114.     for (t = tstr; t->name != NULL; t++)
  1115.         TCalloc(t, tgetstr(t->name, &area));
  1116.     }
  1117.     if (Val(T_co) < 2)
  1118.     Val(T_co) = 80;        /* just in case */
  1119.     if (Val(T_li) < 1)
  1120.     Val(T_li) = 24;
  1121.  
  1122.     T_Cols = Val(T_co);
  1123.     T_Lines = Val(T_li);
  1124.     if (T_Tabs)
  1125.     T_Tabs = Val(T_pt);
  1126.     T_HasMeta = Val(T_km);
  1127.     T_CanCEOL = GoodStr(T_ce);
  1128.     T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
  1129.     T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
  1130.     T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
  1131.     if (GoodStr(T_me) && GoodStr(T_ue))
  1132.     me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
  1133.     else
  1134.     me_all = 0;
  1135.     if (GoodStr(T_me) && GoodStr(T_se))
  1136.     me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
  1137.  
  1138.  
  1139. #ifdef DEBUG_SCREEN
  1140.     if (!T_CanUP) {
  1141.     xprintf("tcsh: WARNING: Your terminal cannot move up.\n");
  1142.     xprintf("Editing may be odd for long lines.\n");
  1143.     }
  1144.     if (!T_CanCEOL)
  1145.     xprintf("no clear EOL capability.\n");
  1146.     if (!T_CanDel)
  1147.     xprintf("no delete char capability.\n");
  1148.     if (!T_CanIns)
  1149.     xprintf("no insert char capability.\n");
  1150. #endif /* DEBUG_SCREEN */
  1151.  
  1152.  
  1153.  
  1154. #ifdef SIG_WINDOW
  1155.     (void) GetSize(&lins, &cols);    /* get the correct window size */
  1156.     ChangeSize(lins, cols);
  1157.  
  1158. # ifdef BSDSIGS
  1159.     (void) sigsetmask(omask);    /* can change it again */
  1160. # else /* BSDSIGS */
  1161.     (void) sigrelse(SIG_WINDOW);
  1162. # endif /* BSDSIGS */
  1163. #else /* SIG_WINDOW */
  1164.     ChangeSize(Val(T_li), Val(T_co));
  1165. #endif /* SIG_WINDOW */
  1166.  
  1167.     BindArrowKeys();
  1168. }
  1169.  
  1170. #ifdef SIG_WINDOW
  1171. /* GetSize():
  1172.  *    Return the new window size in lines and cols, and
  1173.  *    true if the size was changed. This can fail if SHIN
  1174.  *    is not a tty, but it will work in most cases.
  1175.  */
  1176. int
  1177. GetSize(lins, cols)
  1178.     int    *lins, *cols;
  1179. {
  1180.     *cols = Val(T_co);
  1181.     *lins = Val(T_li);
  1182.  
  1183. #ifdef TIOCGWINSZ
  1184. # define KNOWsize
  1185. # ifndef lint
  1186.     {
  1187.     struct winsize ws;    /* from 4.3 */
  1188.  
  1189.     if (ioctl(SHIN, TIOCGWINSZ, (ioctl_t) &ws) != -1) {
  1190.         if (ws.ws_col)
  1191.         *cols = ws.ws_col;
  1192.         if (ws.ws_row)
  1193.         *lins = ws.ws_row;
  1194.     }
  1195.     }
  1196. # endif /* !lint */
  1197. #else /* TIOCGWINSZ */
  1198. # ifdef TIOCGSIZE
  1199. #  define KNOWsize
  1200.     {
  1201.     struct ttysize ts;    /* from Sun */
  1202.  
  1203.     if (ioctl(SHIN, TIOCGSIZE, (ioctl_t) &ts) != -1) {
  1204.         if (ts.ts_cols)
  1205.         *cols = ts.ts_cols;
  1206.         if (ts.ts_lines)
  1207.         *lins = ts.ts_lines;
  1208.     }
  1209.     }
  1210. # endif /* TIOCGSIZE */
  1211. #endif /* TIOCGWINSZ */
  1212.  
  1213.     return (Val(T_co) != *cols || Val(T_li) != *lins);
  1214. }
  1215.  
  1216. #endif /* SIGWINDOW */
  1217.  
  1218. void
  1219. ChangeSize(lins, cols)
  1220.     int     lins, cols;
  1221. {
  1222.     /*
  1223.      * Just in case
  1224.      */
  1225.     Val(T_co) = (cols < 2) ? 80 : cols;
  1226.     Val(T_li) = (lins < 1) ? 24 : lins;
  1227.  
  1228. #ifdef KNOWsize
  1229.     /*
  1230.      * We want to affect the environment only when we have a valid
  1231.      * setup, not when we get bad settings. Consider the following scenario:
  1232.      * We just logged in, and we have not initialized the editor yet.
  1233.      * We reset termcap with tset, and not $TERMCAP has the right
  1234.      * terminal size. But since the editor is not initialized yet, and
  1235.      * the kernel's notion of the terminal size might be wrong we arrive
  1236.      * here with lines = columns = 0. If we reset the environment we lose
  1237.      * our only chance to get the window size right.
  1238.      */
  1239.     if (Val(T_co) == cols && Val(T_li) == lins) {
  1240.     Char    buf[10];
  1241.     char   *tptr;
  1242.  
  1243.     if (getenv("COLUMNS")) {
  1244.         Itoa(Val(T_co), buf);
  1245.         Setenv(STRCOLUMNS, buf);
  1246.     }
  1247.  
  1248.     if (getenv("LINES")) {
  1249.         Itoa(Val(T_li), buf);
  1250.         Setenv(STRLINES, buf);
  1251.     }
  1252.  
  1253.     if (tptr = getenv("TERMCAP")) {
  1254.         Char    termcap[1024], backup[1024], *ptr;
  1255.         int     i;
  1256.  
  1257.         ptr = str2short(tptr);
  1258.         (void) Strncpy(termcap, ptr, 1024);
  1259.         termcap[1023] = '\0';
  1260.  
  1261.         /* update termcap string; first do columns */
  1262.         buf[0] = 'c';
  1263.         buf[1] = 'o';
  1264.         buf[2] = '#';
  1265.         buf[3] = '\0';
  1266.         if ((ptr = Strstr(termcap, buf)) == NULL) {
  1267.         (void) Strcpy(backup, termcap);
  1268.         }
  1269.         else {
  1270.         i = ptr - termcap + Strlen(buf);
  1271.         (void) Strncpy(backup, termcap, i);
  1272.         backup[i] = '\0';
  1273.         Itoa(Val(T_co), buf);
  1274.         (void) Strcat(backup + i, buf);
  1275.         ptr = Strchr(ptr, ':');
  1276.         (void) Strcat(backup, ptr);
  1277.         }
  1278.  
  1279.         /* now do lines */
  1280.         buf[0] = 'l';
  1281.         buf[1] = 'i';
  1282.         buf[2] = '#';
  1283.         buf[3] = '\0';
  1284.         if ((ptr = Strstr(backup, buf)) == NULL) {
  1285.         (void) Strcpy(termcap, backup);
  1286.         }
  1287.         else {
  1288.         i = ptr - backup + Strlen(buf);
  1289.         (void) Strncpy(termcap, backup, i);
  1290.         termcap[i] = '\0';
  1291.         Itoa(Val(T_li), buf);
  1292.         (void) Strcat(termcap, buf);
  1293.         ptr = Strchr(ptr, ':');
  1294.         (void) Strcat(termcap, ptr);
  1295.         }
  1296.         Setenv(STRTERMCAP, termcap);
  1297.     }
  1298.     }
  1299. #endif /* KNOWsize */
  1300.  
  1301.     ReBufferDisplay();        /* re-make display buffers */
  1302.     ClearDisp();
  1303. }
  1304.